package com.sc.nft.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.google.common.collect.Maps;
import com.sc.nft.dao.*;
import com.sc.nft.entity.*;
import com.sc.nft.entity.vo.*;
import com.sc.nft.enums.*;
import com.sc.nft.exception.GlobalException;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.pool.UserPool;
import com.sc.nft.service.*;
import com.sc.nft.sup.ErrorCode;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 服务接口实现
 *
 * @author Sun
 * @since 2022-07-08 13:20:10
 * @description 由 Mybatisplus Code Generator 创建
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class ActivityInfoServiceImpl implements ActivityInfoService {

    private final ActivityInfoDao activityInfoDao;
    private final ActivityItemDao activityItemDao;
    private final ProductStockService productStockService;
    private final BoxItemService boxItemService;
    private final BoxProductDao boxProductDao;
    private final DigitalCollectionDao digitalCollectionDao;
    private final UserCollectionService userCollectionService;
    private final UserAssetsService userAssetsService;
    private final StaticDataDao staticDataDao;
    private final DigitalCollectionProductInfoDao digitalCollectionProductInfoDao;
    private final ActivityRecordDao activityRecordDao;
    private final UserAssetsDao userAssetsDao;


    @Override
    public RouletteDrawDetailsVO getBlindBoxDetails() {
        UserInfo userInfo = UserPool.getUser();
        List<UserCollection> list = userCollectionService.getListByCollercitonId(userInfo.getId(),78L);
        UserAssets userAssets = userAssetsDao.getByUserIdAndCoinId(userInfo.getId(), CoinCategoryEnum.INTEGRAL.getCode());
        List<ActivityRecord> records = activityRecordDao.getListByUserId(userInfo.getId());
        String lotteryIntegralNum = "10";
        Boolean isEnable = Boolean.FALSE;
        ActivityInfo activityInfo = activityInfoDao.getBlindBoxDetails();
        if(     (list.size() >0)
            && (records.size() ==0)
            && (userAssets.getTokenNum().compareTo(new BigDecimal(lotteryIntegralNum)) > -1)
            && (!(DateTime.now().isBefore(activityInfo.getActivityBeginTime())))
            && (!(DateTime.now().isAfter(activityInfo.getActivityEndTime())))){

            isEnable = Boolean.TRUE;
        }


        RouletteDrawDetailsVO rouletteDrawDetailsVO = BeanUtil.toBean(activityInfo, RouletteDrawDetailsVO.class);
        rouletteDrawDetailsVO.setIsEnable(isEnable);

        return rouletteDrawDetailsVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LotteryVO lotteryById(Long id) throws GlobalException {
        UserInfo user = UserPool.getUser();

        ActivityInfo activityInfo = activityInfoDao.getById(id);

        //校验用户
        String lotteryIntegralNum = verifyUser(user,activityInfo);
        //抽奖
        ActivityItem activityItem = lottery(id);


        if(ObjectUtil.isEmpty(activityItem)){
            throw new GlobalRunTimeException(ErrorCode.THE_SYSTEM_IS_BUSY_PLEASE_TRY_AGAIN_LATER);
        }

        //减库存
        activityItemDao.subActivityItemStock(activityItem,1);
        //减去积分
        userAssetsService.subIntegralByUserId(new BigDecimal("10"),user.getId(),CoinCategoryEnum.INTEGRAL,AssetChangeLogEnum.LOTTERY,id,activityInfo.getActivityName());
        //把奖励添加到用户账户
        switch (activityItem.getItemType()){
            case BLIND_BOX:
                String lotteryProductId = staticDataDao.getByType("lottery_product_id").getValue();
                DigitalCollectionProductInfo digitalCollectionProductInfo = digitalCollectionProductInfoDao.getById(Long.valueOf(lotteryProductId));
                addUserCollection(digitalCollectionProductInfo,user.getId());
                break;
            case INTEGRAL:
                userAssetsService.addIntegralByUserId(new BigDecimal(lotteryIntegralNum),user.getId(), CoinCategoryEnum.INTEGRAL, AssetChangeLogEnum.LOTTERY,id,activityInfo.getActivityName());
                break;
            default:
                throw new GlobalRunTimeException(ErrorCode.THE_SYSTEM_IS_BUSY_PLEASE_TRY_AGAIN_LATER);
        }

        //添加抽奖记录
        ActivityRecord activityRecord = new ActivityRecord();
        activityRecord.setUserId(user.getId());
        activityRecord.setActivityId(id);
        activityRecord.setActivityItemId(activityItem.getId());
        activityRecord.setActivityItemName(activityItem.getActivityItemName());
        activityRecord.insert();

        LotteryVO lotteryVO = new LotteryVO();
        lotteryVO.setMsg(activityItem.getActivityItemName());
        lotteryVO.setPrizeId(activityItem.getId());
        return lotteryVO;


    }

    @Override
    public ArrayList<LotteryRecordVO> getLotteryRecord() {
        UserInfo user = UserPool.getUser();

        List<ActivityRecord> listByUserId = activityRecordDao.getListByUserId(user.getId());
        ArrayList<LotteryRecordVO> lotteryRecordVOS = new ArrayList<>();
        for (ActivityRecord activityRecord : listByUserId) {
            LotteryRecordVO lotteryRecordVO = new LotteryRecordVO();
            lotteryRecordVO.setPrizeName(activityRecord.getActivityItemName());
            lotteryRecordVO.setUserName(user.getNickName());
            lotteryRecordVO.setCreateTime(activityRecord.getCreateTime());
            lotteryRecordVOS.add(lotteryRecordVO);
        }
        return lotteryRecordVOS;
    }

    @Override
    public List<LotteryRecordListVO> getRollingRecord() {
        return  activityRecordDao.getLotteryRecordList();
    }

    @Override
    public FrisbeeActivityPorudctVO getFrisbeeActivityPorudct() {
        DigitalCollectionProductInfo byId = digitalCollectionProductInfoDao.getById(508L);
        return BeanUtil.copyProperties(byId, FrisbeeActivityPorudctVO.class);
    }


    @Override
    public IsJoinFrisbeeActivityVO isJoinFrisbeeActivityByUser(UserInfo user) {
        IsJoinFrisbeeActivityVO isJoinFrisbeeActivityVO = new IsJoinFrisbeeActivityVO();
        // 0:限一份   未登录,已登录,未参加过活动
        // 1:已领取   已登录,已参加过活动
        // 2:以抢空   库存不足
        // 3:已结束   活动结束

        ActivityInfo activityInfo = activityInfoDao.getById(2L);
        if(DateTime.now().isAfter(activityInfo.getActivityEndTime())){
            isJoinFrisbeeActivityVO.setIsJoin(Boolean.FALSE);
            isJoinFrisbeeActivityVO.setReason(3);
            return isJoinFrisbeeActivityVO;
        }

        ProductStock productStock = productStockService.getProductStock(508L, null, null);
        if(productStock.getUsableCount()<=0){
            isJoinFrisbeeActivityVO.setIsJoin(Boolean.FALSE);
            isJoinFrisbeeActivityVO.setReason(2);
            return isJoinFrisbeeActivityVO;
        }

        //用户未登录
        if(ObjectUtil.isNull(user)){
            isJoinFrisbeeActivityVO.setIsJoin(Boolean.FALSE);
            isJoinFrisbeeActivityVO.setReason(0);
            return isJoinFrisbeeActivityVO;
        }

        //用户 已登录  已经参加过活动
        Integer count = activityRecordDao.getCountByUserIdAndActivityId(user.getId(), 2L);
        if(count>=1){
            isJoinFrisbeeActivityVO.setIsJoin(Boolean.FALSE);
            isJoinFrisbeeActivityVO.setReason(1);
            return isJoinFrisbeeActivityVO;
        }

        //已登录 未参加过活动
        if(count==0){
            isJoinFrisbeeActivityVO.setIsJoin(Boolean.TRUE);
            isJoinFrisbeeActivityVO.setReason(0);
            return isJoinFrisbeeActivityVO;
        }

        //已登录 未参加过活动
        isJoinFrisbeeActivityVO.setIsJoin(Boolean.TRUE);
        isJoinFrisbeeActivityVO.setReason(0);
        return isJoinFrisbeeActivityVO;

    }


    /**
     * 抽奖
     * @param id
     * @return
     */
    private ActivityItem lottery(Long id){
        List<ActivityItem> list = activityItemDao.getListByActivityId(id);
        if(list.size() == 1){
            return activityItemDao.getById(list.get(0).getId());
        }

        int sum = list.stream().mapToInt(ActivityItem::getUsableCount).sum();

        Map<Long, LotteryIndexRange> map = Maps.newHashMap();
        int idx=0;
        for (ActivityItem activityItem : list) {
            map.put(activityItem.getId(),new LotteryIndexRange(idx+1,idx+activityItem.getUsableCount()));
            idx+=activityItem.getUsableCount();
        }
        int  result = RandomUtil.randomInt(1,sum);
        for (Map.Entry<Long, LotteryIndexRange> entrty : map.entrySet()) {
            LotteryIndexRange indexRange = entrty.getValue();
            if(indexRange.min<=result&&indexRange.max>=result){
                return activityItemDao.getById(entrty.getKey());
            }
        }

        return null;
    }

    @AllArgsConstructor
    class LotteryIndexRange{
        private int min;
        private int max;
    }

    /**
     * 添加到个人藏品
     *
     * @param digitalCollectionProductInfo
     * @param userId
     * @throws GlobalException
     */
    private void addUserCollection(DigitalCollectionProductInfo digitalCollectionProductInfo, Long userId) throws GlobalException {
        //插入用户拥有的藏品
        Long productId = digitalCollectionProductInfo.getId();
        Long collectionId = null;
        boolean isOpen = false;
        Long boxId = null;
        String boxTitle = null;
        String boxImage = null;
        //如果兑换的是盲盒
        productStockService.subIntegralStock(productId, digitalCollectionProductInfo.getRelationId(), null, 1, userId, CommodityType.INVITE_TASKS);

        BoxItem boxItem = boxItemService.openBoxByInviteProbability(productId, digitalCollectionProductInfo.getRelationId(),userId);
        collectionId = boxItem.getCollectionId();
        //减去盲盒库存
        productStockService.subIntegralStock(productId, digitalCollectionProductInfo.getRelationId(), boxItem.getId(), 1, userId, CommodityType.INVITE_TASKS);
        BoxProduct boxProduct = boxProductDao.getById(digitalCollectionProductInfo.getRelationId());
        boxId= boxProduct.getId();
        boxTitle = boxProduct.getFirstTitle();
        boxImage= digitalCollectionProductInfo.getCreationContent();

        DigitalCollection digitalCollection = digitalCollectionDao.getById(collectionId);
        UserCollection userCollection = userCollectionService.addCollection(userId,null,digitalCollection.getId(), IdUtil.getSnowflakeNextIdStr(),digitalCollection.getCreationContent(),digitalCollection.getLevel(),digitalCollection.getFirstTitle(),
                digitalCollection.getUserCreatorId(), ReceivedCollectionType.LOTTERY,boxId,boxTitle,boxImage,isOpen,productId,0L,0L,digitalCollectionProductInfo.getProductNum(),0,null,null,AddCollectionEnum.STAIR,null,null,false);
        //添加藏品流转记录
        CollectionCirculatingRecord collectionCirculatingRecord = new CollectionCirculatingRecord();
        collectionCirculatingRecord.setCommodityType(CommodityType.LOTTERY);
        collectionCirculatingRecord.setTypeClassify(digitalCollectionProductInfo.getTypeClassify());
        collectionCirculatingRecord.setUserId(userId);
        collectionCirculatingRecord.setCollectionId(digitalCollection.getId());
        collectionCirculatingRecord.setReceivedCollectionType(ReceivedCollectionType.LOTTERY);
        collectionCirculatingRecord.setFromUserCollection(userCollection.getId());
        collectionCirculatingRecord.setToUserCollection(userCollection.getId());
        collectionCirculatingRecord.insert();
    }

    private String verifyUser(UserInfo userInfo,ActivityInfo activityInfo){


        if(DateTime.now().isBefore(activityInfo.getActivityBeginTime())){
            throw new GlobalRunTimeException(ErrorCode.NOT_BEGIN);
        }

        if(DateTime.now().isAfter(activityInfo.getActivityEndTime())){
            throw new GlobalRunTimeException(ErrorCode.ALREADY_END);
        }



        String lotteryIntegralNum = staticDataDao.getByType("lottery_integral_num").getValue();


        List<UserCollection> list = userCollectionService.getListByCollercitonId(userInfo.getId(),78L);


        UserAssets userAssets = userAssetsDao.getByUserIdAndCoinId(userInfo.getId(), CoinCategoryEnum.INTEGRAL.getCode());
        if(userAssets.getTokenNum().compareTo(new BigDecimal("10"))   == -1){
            throw new GlobalRunTimeException(ErrorCode.INTEGRAL_NOT_ENOUGH);
        }

        List<ActivityRecord> records = activityRecordDao.getListByUserId(userInfo.getId());
        if(records.size()>0){
            throw new GlobalRunTimeException(ErrorCode.YOU_HAVE_RUN_OUT_OF_TIMES);
        }
        return lotteryIntegralNum;
    }
}